# python函数是指组织好的、可重复使用的、用来实现单一或相关联功能的代码段。
# python函数包含系统中自带的一些函数、第三方函数、以及用户自定义的函数。
# 自定义函数：将一段有规律的重复的代码定义为函数，来达到一次编写多次调用的目的。使用函数可以提高编写代码的效率和代码的重复利用率。
# 函数定义：
# def 函数名(x,y):#参数列表
#     '''      #注释说明函数的功能,要传递的参数的作用等
#     函数说明
#     :param x: 形参x的说明
#     :param y: 形参y的说明
#     :return: #返回值的说明
#     '''
#     函数体      #该函数被调用后，要执行的功能代码
# 函数的参数和返回值可以省略
# 函数调用：
# 函数名(参数值)即可调用该函数  #也就是执行函数
def xiaozhang():
    '''xiaozhang函数可以打印小张个人的信息'''
    print('小张的身高是%f'%1.73)
    print('小张的体重是%f'%160)
    print('小张的爱好是%s'%'唱歌')
    print('小张的专业是%s'%'计算机信息管理')
xiaozhang()# 鼠标悬停，查看调用函数的说明文档
print('=====================================')
# 多次去打印出小张的信息，无需参数就能完成工作，因此括号内是空的
# 以下输出不同人的信息，可以通过传入参数来解决
# 函数的定义
def printInfo(name,height,weight,hobby,pro):
    '''
    这个函数是用来打印个人信息的，是对信息显示的组合
    :return:
    '''
    print('%s的身高是%f' %(name,height))
    print('%s的体重是%f' %(name,weight))
    print('%s的爱好是%s' %(name,hobby))
    print('%s的专业是%s' %(name,pro))
# 函数的调用
printInfo('小李',189,200,'打王者','咨询师')
print('---------------------------------------------------')
printInfo('peter',175,160,'码代码','计算机应用')
# 函数参数：函数参数是用于传递信息给函数的值或变量。函数参数允许你向函数传递数据，以便函数能够在其执行过程中使用这些数据执行特定的操作或计算。参数使得函数能够在不同的情境下执行相似的操作，因为每次调用函数时，传递的参数值可以不同。
# 形式参数：在定义函数时，函数名后面括号中的参数为"形式参数"，形式参数是在函数定义中声明的将要使用的参数，用来接收传递给函数的值，以便函数在执行时可以进行操作。形式参数是实际参数的占位符。在函数被调用之前，形式参数本身不存储任何值。它们的作用是在函数调用时提供一个接收实际参数值的机制。形式参数在函数体内可以被视为变量名(但形参本身并不会在函数被调用前占用内存空间)，等待被赋予具体的值(实际参数则就是变量值)，以便函数在执行时可以进行操作。
# 实际参数：在调用一个函数时，函数名后面括号中的参数为"实际参数"，实际参数是在函数执行时真正使用的参数值，实际参数是在函数调用时提供的参数值，用来传递给函数的具体数据。实际参数的值被传递给函数的形式参数，使函数能够在执行时使用这些值进行操作。实际参数是函数调用中的实际值，可以是常量、变量、表达式等。
# Python中根据传参方式不同函数参数分为几种不同的类型：
# 位置参数(必备参数)（Positional Arguments）：这些参数不限类型但要根据它们在函数定义中的位置进行匹配。调用函数时，传递的参数按照定义的顺序进行匹配。
# 如果形式参数是位置参数，在调用函数时，传递的实际参数的数量和位置必须与定义的形式参数的数量和位置一致
def sum(a,b):#形式参数(形参不占用内存地址)
    sum=a+b
    print(sum)
sum(20,15)#实际参数(实参的值会被存储在形参所对应的局部变量中，这些局部变量会占用内存地址。)
# 关键字参数（Keyword Arguments）：这些参数通过参数名进行匹配，可以不按照函数定义的顺序传递。关键字参数提供了更好的可读性和灵活性。
# 默认参数(缺省参数)（Default Arguments）：在函数定义时，可以为参数设置默认值。如果调用函数时没有传递对应的参数值，将使用默认值，即可以按需覆盖。
def sum1(a=20,b=30):#指定默认的形式参数必须在位置参数的最后
    '''用于两个整数求和'''
    print('默认参数使用=%d'%(a+b))
# 默认参数调用
sum1()
sum1(10)
# 可变参数(不定长参数)：Python支持接受不定数量的参数，分为两种类型：
# 不定长位置参数（Arbitrary Positional Arguments）：通过在参数前面添加星号 *，将接收任意多个实际参数作为元组传递给函数。
def getComputer(*args):# *后面为元组名,args表示接收可变长的参数
    '''
    计算累加和
    :param args:可变长的参数类型
    :return:
    '''
    print(args)
    result=0
    for item in args:
        result+=item
        pass
    print('result=%d'%result)

getComputer(1,2,3,4,5,6)
getComputer(1)

# 不定长关键字参数（Arbitrary Keyword Arguments）：通过在参数前面添加双星号 **，将接收任意多个类似关键字参数一样显示赋值的实际参数作为字典传递给函数。
def keyFunc(**kwargs):
    print(kwargs)
keyFunc(name='peter',age=26)
dictA={'name':'leo','age':35}
keyFunc(**dictA)#使用一个已经存在的字典作为函数的可变参数，可以在字典的名称前加**。
# 混合使用
def complexFunc(*args,**kwargs):
    print(args)
    print(kwargs)
complexFunc(1,2,3,4)
print('-------------')
complexFunc(1,2,3,4,name='刘德华')
print('-------------')
complexFunc(age=36)
# def TestMup(**kwargs,*args):#错误，不定长位置参数必须放在不定长关键字参数之前
# Python中规定了定义函数参数的顺序：
# (关键字参数顺序可以不受限制)
# 1，位置参数
# 2，默认参数
# 3，不定长位置参数 (*args)
# 4，关键字参数
# 5，不定长关键字参数 (**kwargs)
# 这个顺序是有一定的逻辑依据的：
# 1，位置参数在调用函数时必须被提供值，而不定长参数允许你传递任意数量的值。
# 2，默认参数是指在函数定义时给参数指定一个默认值，调用函数时可以省略这些参数，默认参数必须定义在位置参数之后，违反顺序会直接触发 SyntaxError。
# 3.不定长位置参数(*args)用来捕获额外的位置参数，而不定长关键字参数(**kwargs)用来捕获额外的关键字参数。
# 4.不定长位置参数在捕获位置参数时，函数会封装成一个元组，因此其顺序是重要的。不定长关键字参数在捕获关键字参数时，函数会封装成一个字典，因此关键字参数的顺序并不重要。
# 如果你把不定长位置参数放在不定长关键字参数之后，Python会产生歧义。因为不定长关键字参数会捕获所有传递的关键字参数，导致不定长位置参数无法正常捕获剩余的位置参数。所以，为了避免这种歧义，Python规定了参数的顺序。
# 在函数定义中，如果没有特殊标记（如默认值、*、**）的情况下，参数默认是位置参数。但在函数调用时，你可以使用关键字参数的方式来传递值，从而避免按照参数的顺序传递。这就是关键字参数的优势。
# 若要让不定长位置参数（*args）和默认参数同时存在且互不影响，需将默认参数定义在 *args 之后，并强制其作为关键字参数使用。这样即使你传递了多个位置参数，默认参数仍会保持默认值，除非显式通过关键字指定。
# 函数返回值：
# 在python中，可以在函数体内使用return语句为函数指定返回值。
# 函数的返回值是指函数执行完毕之后返回给调用者的结果，可以使用变量来接收，用逗号分隔的多个返回值也可以对应多个变量接收，一个变量接收多个返回值会返回一个元组。
# 该返回值可以是任意类型，并且无论return语句出现在函数的什么位置，只要得到执行，就会直接结束函数的执行，return后面的代码将不会执行。
# 没有return语句时，将返回None，即空值。
def Sum(a,b):
    sum=a+b
    return sum#将计算的结果返回
rs=Sum(10,30)#函数的返回值返回到调用的地方，可以这样保存返回结果
print(Sum(10,30))
def calComputer(num):
    li=[]
    result=0
    i=1
    while i<=num:
        result+=i
        i+=1
    li.append(result)
    return li#会返回列表类型数据
value=calComputer(10)#保存返回的列表类型的数据
print(type(value))#value类型
print(value)
# 函数嵌套
def fun1():
    print("开始1")
    print("执行代码省略")
    print("结束1")
def fun2():
    print("开始2")
    # 调用第一个函数
    fun1()
    print("结束2")
fun2()#调用函数2
# 函数的分类：
# 1.根据参数分类:有参函数、无参函数。
# 2. 根据返回值分类:有返回值函数、无返回值函数。
# 3. 根据定义者分类:系统函数、第三方函数。
# (四种基本类型：有参数有返回值，有参数无返回值，无参数有返回值，无参数无返回值)
